<?

class objInterface{
	public $id = 0;
	public $device_id = 0;
	public $ifIndex = 0;
	public $ifName = '';
	public $ifDescr = '';
	public $ifType = '';
	public $ifPhysAddress = '';
	public $ifMtu = 0;
	public $ifHighSpeed = 0;
	public $ignore = false;
	public $ifInOctets = 0;
	public $ifOutOctets = 0;
	public $lastOutOctets = 0;
	public $lastInOctets = 0;
	public $inOctetsRate = 0;
	public $outOctetsRate = 0;
	public $lastPolled = 0;

	public function __construct($cfg=array()){	
		if (is_array($cfg) || is_object($cfg)) {
			$this->processFields($cfg);
		} 
		
		if ($this->device_id>0 && $this->ifIndex>0) {
			$this->load();
		}
		$this->disablePorts();
	}
	
	public function load() {
		global $nms;
		//echo 'Loading Interface Details'.chr(10);
		$sql = "SELECT *, UNIX_TIMESTAMP(lastPolled) AS lastPolled FROM interfaces WHERE device_id=".$this->device_id." AND ifIndex=".$this->ifIndex." LIMIT 1;";
		//echo 'Load SQL: '.$sql.chr(10);
		$result = $nms->db->getObject($sql);
		$this->processFields($result);		
	}
	
	public function processFields($fields=array()) {
		//print_r($fields);
		if (is_array($fields) || is_object($fields)) {		
			foreach ($fields AS $name=>$value) {
				switch ($name) {
					case 'id':
					case 'ifIndex':
					case 'ifSpeed':
					case 'ifHighSpeed':
					case 'device_id':
					case 'inOctetsRate':
					case 'outOctetsRate':
						$this->$name = (int)$value;
						break;
					case 'ifDescr':
					case 'ifType':
					case 'ifPhysAddress':
					case 'ifName':
					case 'ifMtu':
					case 'ifType':
					case 'ifAlias':
					case 'ifAdminStatus':
					case 'ifOperStatus':
						$this->$name = $value;
						break;
					case 'ifInOctets':
					case 'ifOutOctets':
					case 'lastInOctets':
					case 'lastOutOctets':
					case 'lastPolled':
						$this->$name = $value;
						break;
					case 'ignore':
					case 'disabled':
						$this->ignore = (bool)$value;
						break;
				}
			}
			
		}
		
	}
	protected function disablePorts() {
		if (!empty($this->ifType)) {
			if (
				preg_match("/software/", $this->ifType) ||
				preg_match("/irtual/", $this->ifType) ||
				preg_match("/serial/", $this->ifType) ||
				$this->ifType == 24 ||
				$this->ifType == 1 || 
				$this->ifType == 3 || 
				$this->ifType == 4 
			) {
				$this->ignore = true;
			}
		}
	
	}
	
	public function save($data=array()) {
		global $nms;
		// Process passed data into object
		$this->processFields($data);
		if ($this->device_id>0) {
			if ($this->id>0) {
				// It is already in the database just update details
				if ($this->update()) {
					return true;
				} else {
					return false;
				}
			} else {
				// Check if this interface is already in the database
				$sql = "SELECT id FROM interfaces WHERE device_id=".$this->device_id." AND ifIndex=".$this->ifIndex." LIMIT 1;";
				$result = $nms->db->getObject($sql);
				if (is_object($result) && $result->id > 0) {
					$this->id = $result->id;
					// Update Existing Interfave
					if ($this->update()) {
						return true;
					} else {
						return false;
					}			
				} else {
					// Insert New Interface
					if ($this->insert()) {
						return true;
					} else {
						return false;
					}
				}
			}	
		} else {
			print_r($this);
			echo 'No Device ID'.chr(10);
			return false;
		}
	}
	
	public function update() {
		global $nms;
		$fields = array();
		if (!empty($this->id)) {
			foreach ($this AS $name=>$value) {
				switch ($name) {
					case 'ignore':
						//$fields[] = $name."=".(int)$value;
						break;
				}
			}		
			$fields[] = "lastPolled=NOW()";
			$fields[] = "lastInOctets=".(float)$this->ifInOctets;
			$interval = time()-$this->lastPolled;
			
			$rate = $interval>0?round((($this->ifInOctets-$this->lastInOctets)*8)/($interval),0):0;
			$fields[] = "inOctetsRate=".($rate<0?0:$rate);
			$fields[] = "lastOutOctets=".$this->ifOutOctets;
			$rate = $interval>0?round((($this->ifOutOctets-$this->lastOutOctets)*8)/($interval),0):0;
			$fields[] = "outOctetsRate=".($rate<0?0:$rate);
			if (!empty($fields)) {
				$sql = "UPDATE interfaces SET ".implode(',',$fields)." WHERE id=".$this->id.";";
				if ($nms->db->query($sql)) {
					return true;
				} else {
					return false;
				}
			} else {
				return false;
			}
		} else {
			return false;
		}
	}
	
	
	private function insert() {
		global $nms;
		$fields = array();
		$values = array();
		if ($this->device_id>0) {
			foreach ($this AS $name=>$value) {
				switch ($name) {
					case 'device_id':
					case 'ifIndex':
						$fields[] = $name;
						$values[] = (int)$value;				
						break;
				}
			}
			
			if (!empty($fields) && !empty($values)) {
				$fields[] = 'lastInOctets';
				$values[] = (int)$this->ifInOctets;
				$fields[] = 'lastOutOctets';
				$values[] = (int)$this->ifOutOctets;
				$fields[] = 'inOctetsRate';
				$values[] = 0;
				$fields[] = 'outOctetsRate';
				$values[] = 0;
				$fields[] = 'lastPolled';
				$values[] = 'NOW()';
				$sql = "INSERT INTO interfaces (".implode(',',$fields).") VALUES (".implode(',',$values).");";
				if ($nms->db->query($sql)) {
					$this->id = $nms->db->insertID;
					return true;
				} else {
					echo 'SQL: '.$sql.chr(10);
					return false;
				}
			} else {
				return false;
			}
		} else {
			return false;
		}
	}
	
	public function formatBytes($bytes, $precision = 2) { 
 	   $units = array('b', 'Kb', 'Mb', 'Gb', 'Tb'); 
   
    	$bytes = max($bytes, 0); 
	    $pow = floor(($bytes ? log($bytes) : 0) / log(1000)); 
    	$pow = min($pow, count($units) - 1); 
   
	    $bytes /= pow(1000, $pow); 
    	return round($bytes, $precision) . ' ' . $units[$pow]; 
	}

	public function getDescription($len=32) {
		$output = array();
		if (empty($this->ifName)) {
			if (strlen($this->ifDescr) > $len) {
				$output = substr($this->ifDescr,0,$len).'...';
			} else	$output = $this->ifDescr;
		} else {
			$output = $this->ifName;
			if (!empty($this->ifAlias)) {
				$output .= ' - '.$this->ifAlias;
			}
		}
	
		return $output;
	}
	public function getSpeed($format=true) {
		if ($this->ifSpeed > 0) {
			if ($format) {
				return $this->formatBytes($this->ifSpeed,0);
			} else return $this->ifSpeed;
		} else {
			return '';
		}
	}
	
	public function getBandwidth($format=true) {
		if ($this->ifSpeed > 0) {
			if ($format) {
				return $this->formatBandwidth($this->ifSpeed,0);
			} else return $this->ifSpeed;
		} else {
			return '';
		}
	}
	public function formatBandwidth($bytes, $precision = 2) { 
 		$units = array('', 'K', 'M', 'G', 'T'); 
		$bytes = max($bytes, 0); 
		$pow = floor(($bytes ? log($bytes) : 0) / log(1000)); 
		$pow = min($pow, count($units) - 1); 
		$bytes /= pow(1000, $pow); 
		return round($bytes, $precision) . ' ' . $units[$pow]; 
	}
	
	
	public function getHighSpeed($format=true) {
		if ($this->ifHighSpeed > 0) {
			if ($format) {
				return $this->formatBytes($this->ifHighSpeed,0);
			} else return $this->ifHighSpeed;
		} else {
			return '';
		}
	}
	
	public function setrrd($path,$data,$step=60) {
		$path = $this->getRrdPath();
		$poll_period = $data['last_polled']-$this->last_polled;
		// Process Into Interface Objects
		foreach ($data AS $name=>$value) {
			switch ($name) {
				case 'ifInOctets':
				case 'ifOutOctets':
				case 'ifInErrors':
				case 'ifOutErrors':
				case 'ifInUcastPkts':
				case 'ifOutUcastPkts':
				case 'ifInNUcastPkts':
				case 'ifOutNUcastPkts':
					$diff = $value - $this->$name;
					$rateName = $name.'_rate';
					$this->$rateName = $poll_period>0?$diff/$poll_period:0;
					$this->$name = $value;
					break;
			}
		}
		// Calculate Rates
		
		
		
		// Update RRD Data File
		if (!is_file($path)) {
			$opts = array(
				'--step',$step,
				'--start','0',
				'DS:INOCTETS:COUNTER:600:0:12500000000',
				'DS:OUTOCTETS:COUNTER:600:0:12500000000',
				'DS:INERRORS:COUNTER:600:0:12500000000',
				'DS:OUTERRORS:COUNTER:600:0:12500000000',
				'DS:INUCASTPKTS:COUNTER:600:0:12500000000',
				'DS:OUTUCASTPKTS:COUNTER:600:0:12500000000',
				'DS:INNUCASTPKTS:COUNTER:600:0:12500000000',
				'DS:OUTNUCASTPKTS:COUNTER:600:0:12500000000',
				'RRA:AVERAGE:0.5:1:600',
				'RRA:AVERAGE:0.5:6:700',
				'RRA:AVERAGE:0.5:24:775',
				'RRA:AVERAGE:0.5:288:797',
				'RRA:MAX:0.5:1:600',
				'RRA:MAX:0.5:6:700',
				'RRA:MAX:0.5:24:775',
				'RRA:MAX:0.5:288:797'
			);
			
			
			if (rrd_create($path, $opts, count($opts)) == 0) { 
				echo 'Error: '.rrd_error().chr(10);
				// Log Error
				return false;
			}
		}
		if (is_array($data)) {
			$rrd = array();
			$rrd[] = 'N';
			$rrd[] = isset($data['ifInOctets'])?$data['ifInOctets']:0;
			$rrd[] = isset($data['ifOutOctets'])?$data['ifOutOctets']:0;		
			$rrd[] = isset($data['ifInErrors'])?$data['ifInErrors']:0;		
			$rrd[] = isset($data['ifOutErrors'])?$data['ifOutErrors']:0;
			$rrd[] = isset($data['ifInUcastPkts'])?$data['ifInUcastPkts']:0;		
			$rrd[] = isset($data['ifOutUcastPkts'])?$data['ifOutUcastPkts']:0;
			$rrd[] = isset($data['ifInNUcastPkts'])?$data['ifInNUcastPkts']:0;		
			$rrd[] = isset($data['ifOutNUcastPkts'])?$data['ifOutNUcastPkts']:0;
			echo 'Interface Traffic: '.implode(':',$rrd).chr(10);
			$this->save();
			if (rrd_update($path,implode(':',$rrd)) == 0) {
				return false;
			} else {
				return true;
			}
		} else {
			// Log Error
			return false;			
		}
	}
	public function getRrdPath() {
		global $nms;
		$path = $nms->getPath('rrd').$this->device_id.'/';
		if (!is_dir($path)) { mkdir($path,0777,true);}	
		return $path.'interface_'.$this->ifIndex.'.rrd';
	}	
	public function getGraphPath($params=array()) {return $this->generateGraphPath($params);}
	public function generateGraphPath($params=array()) {
		global $nms;
		return $nms->getPath('cache').'graph_device_'.$this->device_id.'_interface_'.$this->ifIndex.'_'.$params['type'].'_'.$params['start'].'.png';	
	}
	public function graph($params=array()) {	
//		echo 'PARAMS: <pre>'.print_r($params,1).'</pre><br/>';
		$path = $this->getRrdPath();
		$className = 'graph'.ucfirst($params['type']);
		$graph = new $className($path,$params);
		$graph->generate($this->generateGraphPath($params));	
	}
	public function getCurrentThroughput($inout='in') {
		if ($inout== 'in') {
			return $this->formatBytes($this->inOctetsRate);
		} else {
			return $this->formatBytes($this->outOctetsRate);
		}
	}
	
	public function isDown() {
		if ($this->ifAdminStatus == 'up'&& $this->ifOperStatus == 'down') {
			return true;
		} else return false; 
	}
	public function getStatus() {		 
		if ($this->ifAdminStatus == 'down' && $this->ifOperStatus == 'down' || $this->ignore) {
			return 'disabled';
		} elseif ($this->ifAdminStatus == 'up' && $this->ifOperStatus == 'up') {
			return 'up';
		} elseif ($this->ifAdminStatus == 'up' && $this->ifOperStatus == 'down') {
			return 'down';
		} 
	}
	
	public function getType() {
		switch ($this->ifType) {
			case 6: return 'Ethernet Port';	break;
			case 8: return 'Tunnel'; break;
			case 13: return 'Virtual Port'; break;
			case 22: return 'Serial Interface'; break;
			case 23: case 24: case 25: return 'Software Loopback'; break;
			case 62: return 'Fast Ethernet'; break;
			case 71: return '802.11 Wireless Port'; break;
			case 117: return 'Gigabit Ethernet'; break;
			case 135: return 'Layer 2 VLAN'; break;
			case 142:  return 'IP Forward Port'; break;
  			default: return '';
		
		}
	
	}
	
	
}